package com.ruoyi.common.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.annotation.PostConstruct;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;


// 新增
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

@Configuration
@PropertySource("classpath:wxpay.properties") // 加载微信支付配置文件
@ConfigurationProperties(prefix = "wxpayment") // 对应yml中的"wxpay"前缀
@Data
@Slf4j
public class WxPaymentConfig {
    // 微信支付相关参数

    // 商户号
    private String mchId;

    // 商户API证书序列号
    private String mchSerialNo;

    // 商户API私钥文件路径
    private String privateKeyPath;

    // 商户API公钥文件路径
    private String publicCertPath;

    // APIv3密钥
    private String apiV3Key;

    // 商户APIv2密钥
    private String apiV2Key;

    // APPID
    private String appid;

    // APP密钥
    private String appSecret;

    // 微信支付接口域名
    private String domain;

    // 微信支付接口回调地址
    private String notifyDomain;

    // 签名类型
    private String signType;

    // 支付类型
    private String tradeType;

    /**
     * 获取微信平台验证器（用于验签）
     * @return Verifier 实例
     * @throws NotFoundException 未找到验证器时抛出
     */
    public Verifier getWechatPayVerifier() throws NotFoundException {
        // 从证书管理器获取验证器
        return CertificatesManager.getInstance().getVerifier(this.mchId);
    }

    /**
     * 获取商户公钥
     */
    public PublicKey getPublicKey(String publicKeyPath) {
        try (InputStream is = new FileInputStream(publicKeyPath)) {
            // 使用loadCertificate替代loadPublicKey
            return PemUtil.loadCertificate(is).getPublicKey();
        } catch (FileNotFoundException e) {
            throw new RuntimeException("公钥文件不存在：" + publicKeyPath, e);
        } catch (IOException e) {
            throw new RuntimeException("读取公钥文件失败：" + publicKeyPath, e);
        }
    }


    /**
     * 获取商户私钥
     *
     * @param privateKeyPath
     * @return
     * @throws Exception
     */
    public PrivateKey getPrivateKey(String privateKeyPath){

        // 示例：私钥存储在类路径下(相对路径)
//        try (InputStream is = getClass().getResourceAsStream(privateKeyPath)) {
//            if (is == null) {
//                throw new RuntimeException("私钥文件未找到: " + privateKeyPath);
//            }
//            return PemUtil.loadPrivateKey(is);
//        } catch (Exception e) {
//            throw new RuntimeException("读取私钥文件失败", e);
//        }

        // 示例：私钥存储在文件中(绝对路径)
        try {
            // 示例：私钥存储在文件
            return PemUtil.loadPrivateKey(new FileInputStream(privateKeyPath));
        } catch (FileNotFoundException e) {
            throw new RuntimeException("私钥文件不存在", e);
        }
    }

    /**
     * 初始化证书管理器（在Bean初始化阶段执行）
     */
    @PostConstruct
    public void initCertificatesManager() throws GeneralSecurityException,
            IOException, NotFoundException, HttpCodeException {

        // 验证私钥文件是否存在
        File privateKeyFile = new File(privateKeyPath);
        if(!privateKeyFile.exists()) {
            throw new RuntimeException("私钥文件不存在：" + privateKeyPath);
        }

        // 获取商户私钥
        PrivateKey merchantPrivateKey = getPrivateKey(this.privateKeyPath);

        // 创建私钥签名器 私钥的签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(this.mchSerialNo, merchantPrivateKey);

        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();

        // 添加商户信息（确保只执行一次）
        certificatesManager.putMerchant(
                this.mchId,
                new WechatPay2Credentials(this.mchId, privateKeySigner),
                this.apiV3Key.getBytes(StandardCharsets.UTF_8)
        );
    }

    /**
     * 获取微信支付验证器
     *
     * @return WechatPay2Validator 实例
     * @throws NotFoundException 当商户验证器未找到时抛出
     */
    @Bean
    public WechatPay2Validator getWechatPayValidator() throws NotFoundException {
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();

        // 返回验证器实例
        return new WechatPay2Validator(certificatesManager.getVerifier(this.mchId));
    }

    /**
     * 创建微信支付HTTP客户端
     *
     * @return CloseableHttpClient 实例
     * @throws Exception 验证器初始化异常
     */
    @Bean
    public CloseableHttpClient getWxPaymentClient() throws Exception {
        // 获取验证器
        WechatPay2Validator validator = getWechatPayValidator();

        // 获取商户私钥
        PrivateKey merchantPrivateKey = getPrivateKey(this.privateKeyPath);

        // 构建HTTP客户端
        return WechatPayHttpClientBuilder.create()
                .withMerchant(this.mchId, this.mchSerialNo, merchantPrivateKey)
                .withValidator(validator)
                .build();
    }

}
